<?php
/**
 * Form class
 * 
 * @author Mathieu Pheulpin - sokaru91@gmail.com
 *
 */
class Mac_Form
{
    protected $name = null;
    
    protected $method = 'post';
    
    protected $action = '';
    
    protected $class = array();
    
    protected $fileEnabled = false;
    
    protected $oldTokenValue = null;
    
    protected $tokenField = null;
    
    /**
     * Form elements
     * @var array<Form_Element_Abstract>
     */
    protected $elements = array();
    
    public function __construct ($name, array $params = array())
    {
        $this->name = $name;
        
        if (isset($params['method']) && (strtolower($params['method'])==='get')) {
            $this->method = 'get';
        } else {
            $this->method = 'post';
        }
        
        if (isset($params['action'])) {
            $this->action = $params['action'];
        } else {
            $this->action = $_SERVER['REQUEST_URI'];
        }
        
        if (isset($params['class'])) {
            if (is_array($params['class'])) {
                $this->class = $params['class'];
            } else {
                $this->class = array($params['class']);
            }
        }
        
        $tokenName = 'token_'.$name;
        $session = Mac_Session::getNamespace('form_check');
        $this->oldTokenValue = $session->get($tokenName);
        
        $token = sha1(uniqid(null, true));
        $this->tokenField = new Mac_Form_Element_Hidden($tokenName, $token);;
        $session->set($tokenName, $token);
    }
    
    public function addElement ($element)
    {
        if(is_subclass_of($element, 'Mac_Form_Element_Abstract')) {
            $this->elements[$element->getId()] = $element;
        }
    }
    
    public function addElements (array $elements)
    {
        foreach($elements as $element) {
            $this->addElement($element);
        }
    }

    /**
     *
     * @param string $id
     * @return Form_Element_Abstract
     */
    public function getElement ($id)
    {
        if (isset($this->elements[$id])) {
            return $this->elements[$id];
        } else {
            return null;
        }
    }
    
    /**
    *
    * @param string $id
    * @return string
    */
    public function getElementLabel ($id)
    {
        if (isset($this->elements[$id])) {
            $element = $this->elements[$id];
            return $element->getLabel();
        } else {
            return null;
        }
    }
    
    /**
    *
    * @param string $id
    * @return string
    */
    public function getElementValue ($id)
    {
        if (isset($this->elements[$id])) {
            $element = $this->elements[$id];
            return $element->getValue();
        } else {
            return null;
        }
    }
    
    public function isValid ($data = null)
    {
        if ($data === null) {
            $request = new Mac_Controller_HTTPRequest();
            $data = ($this->method === 'post') ? $_POST : $request->getUnorderedParams();
        }
        
        if (!isset($data[$this->tokenField->getName()]) || ($data[$this->tokenField->getName()] != $this->oldTokenValue)) {
            return false;
        }
        
        $valid = true;
        foreach($this->elements as $element) {
            $element->setValue(isset($data[$element->getName()]) ? $data[$element->getName()] : '');
            $valid &= $element->isValid($data);
        }
        return $valid;
    }
    
    public function addClass ($class)
    {
        $this->class[] = $class;
        return $this;
    }
    
    public function setClasses (array $classes)
    {
        $this->class = $classes;
        return $this;
    }
    
    public function openTag ()
    {
        return '<form
            id="'.$this->name.'"
            name="'.$this->name.'"
            method="'.$this->method.'"
            action="'.$this->action.'"
            '.((count($this->class) > 0) ? 'class="'.implode(' ', $this->class).'"' : '').'
            '.(($this->fileEnabled === true) ? 'enctype="multipart/form-data"' : '').'
        >'.$this->tokenField;
    }
    
    public function closeTag ()
    {
        return '</form>';
    }

    public function getMessages ()
    {
        $messages = array();
        foreach($this->elements as $element) {
            $messages[$element->getId()] = $element->getMessages();
        }
        return $messages;
    }
    
    public function enableFileTransfert() {
        $this->fileEnabled = true;
        return $this;
    }
    
    public function clean () {
        foreach($this->elements as $element) {
            $element->setValue(null);
        }
    }
}
